/***********************************************************************************
 @file   
 @author
 @attention
 ***********************************************************************************/
#include "mid_capture.h"
/***********************************************************************************
 * @global param
***********************************************************************************/
uint8_t ir_code[4];              // 用于存放16位用户码+8位键值+8位键值反码
uint8_t ir_decode_ok_flag = 0;   // 解码成功标志位
/***********************************************************************************
 * @brief  NEC红外解码配置宏定义
***********************************************************************************/
#define IS_INFRARED_CUSTOM_PROTOCOL    1
#define NEC_REPEAT_ENABLE              1     /* 1-使能连按功能 0-禁用连按功能 */
#define REPEAT_THRESHOLD               2     /* 连按触发阈值*/
/***********************************************************************************
 * @brief  Timer2配置初始化
***********************************************************************************/
void timer2_config_init(uint16_t period)
{
    uint32_t                  u16ArrValue;
    uint32_t                  u16CntValue;
    stc_bt_mode0_cfg_t        stcBtBaseCfg;
    
    uint32_t    convertPeriod;
  
    DDL_ZERO_STRUCT(stcBtBaseCfg);
    
    Sysctrl_SetPeripheralGate(SysctrlPeripheralBaseTim, TRUE); //Base Timer外设时钟使能
    
    stcBtBaseCfg.enWorkMode = BtWorkMode0;                  //定时器模式
    stcBtBaseCfg.enCT       = BtTimer;                      //定时器功能，计数时钟为内部PCLK
    stcBtBaseCfg.enPRS      = BtPCLKDiv8;                 //PCLK/8  24000000/8=3000000
    
    stcBtBaseCfg.enCntMode  = Bt16bitArrMode;               //自动重载16位计数器/定时器

    stcBtBaseCfg.bEnTog     = FALSE;
    stcBtBaseCfg.bEnGate    = FALSE;
    stcBtBaseCfg.enGateP    = BtGatePositive;
    Bt_Mode0_Init(TIM2, &stcBtBaseCfg);                     //TIM2 的模式0功能初始化
  
    //Timer1配置初始化(周期 = (24000 000/8/1000 0) = 300 = 0.1ms=100us)
    convertPeriod = (period * Sysctrl_GetHClkFreq())/(8*10000);
  
    u16ArrValue = 0x10000 - convertPeriod;
    Bt_M0_ARRSet(TIM2, u16ArrValue);                        //设置重载值(ARR = 0x10000 - 周期)
    
    u16CntValue = 0x10000 - convertPeriod;
    Bt_M0_Cnt16Set(TIM2, u16CntValue);                      //设置计数初值
    
    Bt_ClearIntFlag(TIM2,BtUevIrq);                         //清中断标志   
    Bt_Mode0_EnableIrq(TIM2);                               //使能TIM2中断(模式0时只有一个中断)
    EnableNvic(TIM2_IRQn, IrqLevel2, TRUE);                 //TIM2中断使能
    
    //TIM2 由Ir 中断使能
    Bt_M0_Run(TIM2); 	    
}
/***********************************************************************************
 * @brief  解码端口初始化 输入上拉
***********************************************************************************/
void infared_gpio_init(void)
{
    stc_gpio_cfg_t stcGpioCfg;
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

    stcGpioCfg.enDir = GpioDirIn;
    stcGpioCfg.enDrv = GpioDrvL;
    stcGpioCfg.enPu = GpioPuEnable;
    stcGpioCfg.enPd = GpioPdDisable;
    stcGpioCfg.enOD = GpioOdDisable;
    Gpio_Init(IR_PORT, IR_PIN, &stcGpioCfg);
}
/***********************************************************************************
 * @brief  解码端口取消初始化 输入下拉
***********************************************************************************/
void infared_gpio_deinit(void)
{
    stc_gpio_cfg_t stcGpioCfg;
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

    stcGpioCfg.enDir = GpioDirIn;
    stcGpioCfg.enDrv = GpioDrvL;
    stcGpioCfg.enPu = GpioPuDisable;
    stcGpioCfg.enPd = GpioPdEnable;
    stcGpioCfg.enOD = GpioOdDisable;
    Gpio_Init(IR_PORT, IR_PIN, &stcGpioCfg);
}
/***********************************************************************************
 * @brief  解码流程 100us
***********************************************************************************/
void infared_init(void)
{
    infared_gpio_init();
    timer2_config_init(1);
}
/***********************************************************************************
 * @brief  解码流程 100us
***********************************************************************************/
void infared_decode(void)
{
    /* 电平时间测量相关变量 */
    static unsigned char l_cnt = 0;                 /* 低电平时间计数(单位:100us) */
    static unsigned char h_cnt = 0;                 /* 高电平时间计数(单位:100us) */
    static unsigned char l_cnt_save = 0;            /* 保存的低电平持续时间 */
    static unsigned char h_cnt_save = 0;            /* 保存的高电平持续时间 */
    static unsigned char falling_edge_flag = 0;     /* 下降沿有效标志(高→低跳变) */
    
    /* 解码状态相关变量 */    
    static unsigned char sync_ok_flag = 0;          /* 同步码接收成功标志 */
    static unsigned char bit_value = 0;             /* 当前解码的位值(0/1/2) */
    static unsigned char bit_count = 0;             /* 已接收的位数计数 */
    
#if NEC_REPEAT_ENABLE
    /* 连按功能相关变量 */
    static unsigned char repeat_count = 0;          /* 重复码计数器 */
    static unsigned char last_code[4] = {0};        /* 上次有效按键码存储 */
#endif
     /*测量高低电平持续时间并保存*/
    if(IR_IN() == 0) {  /* 当前为低电平 */
        if(l_cnt == 0) { /* 检测到高→低跳变 */
            h_cnt_save = h_cnt;  /* 保存高电平时间 */
            falling_edge_flag = 1; /* 置位下降沿标志 */
        }
        
        l_cnt++;  /* 低电平时间计数 */
        if(l_cnt > 250) l_cnt = 250; /* 防溢出处理 */
        h_cnt = 0; /* 高电平计数器清零 */
    }
    else {  /* 当前为高电平 */
        if(h_cnt == 0) { /* 检测到低→高跳变 */
            l_cnt_save = l_cnt;  /* 保存低电平时间 */
        }
        
        h_cnt++;  /* 高电平时间计数 */
        if(h_cnt > 250) h_cnt = 250; /* 防溢出处理 */
        l_cnt = 0; /* 低电平计数器清零 */
    }
    /*解码处理部分(在下降沿触发)*/
    if(falling_edge_flag) 
     {
        falling_edge_flag = 0;  /* 清除下降沿标志 */
        
#if NEC_REPEAT_ENABLE
         /*连按码检测处理 NEC协议重复码特征: 9ms低电平 + 2.25ms高电平*/
        if((l_cnt_save >= 85 && l_cnt_save <= 95) &&    /* 9ms低电平(85-95个周期) */
           (h_cnt_save >= 22 && h_cnt_save <= 25))      /* 2.25ms高电平(22-25个周期) */
        {    
            repeat_count++;  /* 重复码计数加1 */
            /* 达到连按阈值后使用上次存储的有效按键码 */
            if(repeat_count >= REPEAT_THRESHOLD) {
                ir_code[0] = last_code[0];
                ir_code[1] = last_code[1];
                ir_code[2] = last_code[2];
                ir_code[3] = last_code[3];
                ir_decode_ok_flag = 1;  /* 置位解码完成标志 */
            }
            return;  /* 重复码处理结束直接返回 */
        }
#endif
        /*位解码处理  根据高低电平时间判断当前位是0还是1*/
        /* 560us低电平 + 560us高电平 → 逻辑0 */
        if((l_cnt_save >= 3 && l_cnt_save <= 7) && 
           (h_cnt_save >= 3 && h_cnt_save <= 7)) 
        {
            bit_value = 0;
        }
        /* 560us低电平 + 1680us高电平 → 逻辑1 */
        else if((l_cnt_save >= 3 && l_cnt_save <= 7) && 
                (h_cnt_save >= 15 && h_cnt_save <= 18)) 
        {
            bit_value = 1;
        }
        /* 其他情况 → 无效位 */
        else 
        {
            bit_value = 2;
        }
        /*数据帧接收处理  NEC协议数据格式: 32位(4字节)*/
        if(sync_ok_flag) 
        {
            /* 有效位处理(0或1) */
            if(bit_value == 0 || bit_value == 1) {
                /* 按位存储到对应字节 */
                if(bit_count < 8) {
                    ir_code[0] |= (bit_value << (bit_count % 8));
                }
                else if(bit_count < 16) {
                    ir_code[1] |= (bit_value << (bit_count % 8));
                }
                else if(bit_count < 24) {
                    ir_code[2] |= (bit_value << (bit_count % 8));
                }
                else if(bit_count < 32) {
                    ir_code[3] |= (bit_value << (bit_count % 8));
                }
                
                /* 32位接收完成 */
                if(bit_count >= 31) 
               {
#if NEC_REPEAT_ENABLE
                    /* 保存当前按键码用于连按处理 */
                    last_code[0] = ir_code[0];
                    last_code[1] = ir_code[1];
                    last_code[2] = ir_code[2];
                    last_code[3] = ir_code[3];
                    repeat_count = 0;  /* 重置连按计数器 */
#endif
                    ir_decode_ok_flag = 1;  /* 置位解码完成标志 */
                    sync_ok_flag = 0;       /* 清除同步标志 */
                }
                
                bit_count++;  /* 位计数器递增 */
            }
            else {
                /* 无效位导致解码错误 */
                sync_ok_flag = 0;  /* 清除同步标志重新开始 */
            }
        }
        /*同步码检测  NEC 9ms低电平 + 4.5ms高电平*/
        if((l_cnt_save >= 85 && l_cnt_save <= 95) &&   /* 9ms低电平 */
           (h_cnt_save >= 42 && h_cnt_save <= 46))   /* 4.5ms高电平 */ 
        {   
            sync_ok_flag = 1;    /* 置位同步成功标志 */
            bit_count = 0;       /* 位计数器清零 */
            /* 数据缓冲区清零 */
            ir_code[0] = 0;
            ir_code[1] = 0;
            ir_code[2] = 0;
            ir_code[3] = 0;
        }
    }
}
#if defined(IS_INFRARED_CUSTOM_PROTOCOL)&&(IS_INFRARED_CUSTOM_PROTOCOL==1)
/***********************************************************************************
* @brief  解码流程
***********************************************************************************/
static void infared_encode(uint8_t* code)
{
    if(code==NULL) return;
    uint8_t  checksum =  code[0] + code[1] + code[2];
    uint16_t data     = (code[1] << 8) | code[2];
    if(ir_code[3] != (checksum & 0xFF))
    {
        return;
    }
    switch(ir_code[0])
    {
        case 0xA0: if(perform_set_df_addr(data))   {menu_good;}else{menu_fail;}break;// 编址               
        case 0xA1: if(perform_zero())              {menu_good;}else{menu_fail;}break;// 校零      
        case 0xA2: if(perform_2288(data))          {menu_good;}else{menu_fail;}break;// 标定
        case 0xA3: if(perform_set_unit(data))      {menu_good;}else{menu_fail;}break;// 设置单位       
        case 0xA4: if(perform_set_precision(data)) {menu_good;}else{menu_fail;}break;// 设置精度 
        case 0xA5: if(perform_set_gas_name(data))  {menu_good;}else{menu_fail;}break;// 设置气体名称
        case 0xA6: if(perform_set_low_alarm(data)) {menu_good;}else{menu_fail;}break;// 设置低报
        case 0xA7: if(perform_set_high_alarm(data)){menu_good;}else{menu_fail;}break;// 设置高报          
        case 0xA8: if(perform_set_range(data))     {menu_good;}else{menu_fail;}break;// 设置量程         
        case 0xA9: if(perform_set_preheat(data))   {menu_good;}else{menu_fail;}break;// 预热时间
        case 0xAA: if(perform_6969())              {menu_good;}else{menu_fail;}break;// 执行6969            
        case 0xAB: if(perform_6868())              {menu_good;}else{menu_fail;}break;// 执行6868
        case 0xAC: break;// 执行6161       
        default:printf("Unknown IR command: %02X\r\n", ir_code[0]);break;
    }
    printf("encode:%02X %02X %02X %02X\r\n",ir_code[0],ir_code[1],ir_code[2],ir_code[3]); 
}
#endif
/***********************************************************************************
 * @brief  解码流程
***********************************************************************************/
void infared_process(void)
{
    if( ir_decode_ok_flag == 1 )
    {
        ir_decode_ok_flag = 0;
        sleep_device_operation_time(IR_NORMAL_TIME); 
        infrared_total(ir_code[2]);
        #if defined(IS_INFRARED_CUSTOM_PROTOCOL)&&(IS_INFRARED_CUSTOM_PROTOCOL==1)
        infared_encode(ir_code);
        #endif
//        printf("IrKey:%02X %02X %02X %02X\r\n",ir_code[0],ir_code[1],ir_code[2],ir_code[3]); 
    }
}
/***********************************************************************************
 * @brief  虚拟激活按键
***********************************************************************************/
void infared_virtual_key(void)
{
    ir_decode_ok_flag = 1;
    ir_code[2] = KEY_OK;
}
/***********************************************************************************
 * @brief  定时器2中断
***********************************************************************************/
void Tim2_IRQHandler(void)
{
    if(TRUE == Bt_GetIntFlag(TIM2, BtUevIrq))
    {
		Bt_ClearIntFlag(TIM2,BtUevIrq); //中断标志清零       
		infared_decode();
    }
}


